﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;

namespace AndreySmirnov.BLToolkitUtils.VSPackage
{
	public static class Extensions
	{
		public static IEnumerable<HierarchyItemDescriptor> EnumChildItems(this IVsHierarchy hierarchy, uint rootItemId)
		{
			object data;
			var hr = hierarchy.GetProperty(rootItemId, (int) __VSHPROPID.VSHPROPID_FirstChild, out data);
			ErrorHandler.ThrowOnFailure(hr);
			var childItemId = GetItemId(data);
			while(childItemId != VSConstants.VSITEMID_NIL)
			{
				yield return hierarchy.GetItemDesctiptor(childItemId);
				hr = hierarchy.GetProperty(childItemId, (int)__VSHPROPID.VSHPROPID_NextSibling, out data);
				ErrorHandler.ThrowOnFailure(hr);
				childItemId = GetItemId(data);
			}
		}
		public static IEnumerable<HierarchyItemDescriptor> EnumChildItems(this IVsHierarchy hierarchy, uint rootItemId, string rootItemName)
		{
			object data;
			var hr = hierarchy.GetProperty(rootItemId, (int) __VSHPROPID.VSHPROPID_FirstChild, out data);
			ErrorHandler.ThrowOnFailure(hr);
			var childItemId = GetItemId(data);
			while(childItemId != VSConstants.VSITEMID_NIL)
			{
				var item = hierarchy.GetItemDesctiptor(childItemId, rootItemName);
				yield return item;
				foreach (var childItem in hierarchy.EnumChildItems(childItemId, item.Caption))
				{
					yield return childItem;
				}
				hr = hierarchy.GetProperty(childItemId, (int)__VSHPROPID.VSHPROPID_NextSibling, out data);
				ErrorHandler.ThrowOnFailure(hr);
				childItemId = GetItemId(data);
			}
		}

		public static HierarchyItemDescriptor GetItemDesctiptor(this IVsHierarchy hierarchy, uint itemId)
		{
			var result = new HierarchyItemDescriptor();
			result.ItemId = itemId;
			result.Hierarchy = hierarchy;
			object data;
			var hr = hierarchy.GetProperty(result.ItemId, (int) __VSHPROPID.VSHPROPID_Caption, out data);
			ErrorHandler.ThrowOnFailure(hr);
			result.Caption = (string) data;
			return result;
		}

		public static HierarchyItemDescriptor GetItemDesctiptor(this IVsHierarchy hierarchy, uint itemId, string rootItemName)
		{
			var result = new HierarchyItemDescriptor();
			result.ItemId = itemId;
			result.Hierarchy = hierarchy;
			object data;
			var hr = hierarchy.GetProperty(result.ItemId, (int) __VSHPROPID.VSHPROPID_Caption, out data);
			ErrorHandler.ThrowOnFailure(hr);
			result.Caption = Path.Combine(rootItemName, (string) data);
			return result;
		}
		/// <summary>
		/// Gets the item id.
		/// </summary>
		/// <param name="pvar">VARIANT holding an itemid.</param>
		/// <returns>Item Id of the concerned node</returns>
		private static uint GetItemId(object pvar)
		{
			if (pvar == null) return VSConstants.VSITEMID_NIL;
			if (pvar is int) return (uint)(int)pvar;
			if (pvar is uint) return (uint)pvar;
			if (pvar is short) return (uint)(short)pvar;
			if (pvar is ushort) return (uint)(ushort)pvar;
			if (pvar is long) return (uint)(long)pvar;
			return VSConstants.VSITEMID_NIL;
		}
	}

	public class HierarchyItemDescriptor
	{
		public uint ItemId { get; set; }
		public IVsHierarchy Hierarchy { get; set; }
		public string Caption { get; set; }
	}
}
